package org.zn.mygateway.plugin.plugin;

import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author： zhangnan
 * @date： 2025/6/18 15:42
 * @description： TODO
 * @modifiedBy：
 * @version: 1.0
 */
public interface MyPlugin {

    /**
     * Process the Web request and (optionally) delegate to the next
     * {@code WebFilter} through the given {@link MyPluginChain}.
     *
     * @param exchange the current server exchange
     * @param chain    provides a way to delegate to the next filter
     * @return {@code Mono<Void>} to indicate when request processing is complete
     */
    Mono<Void> execute(ServerWebExchange exchange, MyPluginChain chain);

    /**
     * return plugin order .
     * This attribute To determine the plugin execution order in the same type plugin.
     *
     * @return int order
     */
    int getOrder();

    /**
     * acquire plugin name.
     * this is plugin name define you must Provide the right name.
     * if you impl AbstractShenyuPlugin this attribute not use.
     *
     * @return plugin name.
     */
    default String named() {
        return "";
    }

    /**
     * plugin is executed.
     * if return true this plugin can not execute.
     *
     * @param exchange the current server exchange
     * @return default false.
     */
//    default boolean skip(ServerWebExchange exchange) {
//        return false;
//    }

    /**
     * plugin is executed.
     * if return true this plugin can not execute.
     *
     * <p>the same for:
     * <pre>
     * <code>Objects.equals(rpcType, typeA.getName())
     * || Objects.equals(rpcType, typeB.getName())
     * || Objects.equals(rpcType, type...getName())
     * </code>
     * </pre>
     *
     * @param exchange the current server exchange
     * @param rpcTypes the skip rpc type list
     * @return current rpcType == someone rpcType
     */
//    default boolean skip(ServerWebExchange exchange, RpcTypeEnum... rpcTypes) {
//        if (ArrayUtils.isEmpty(rpcTypes)) {
//            return false;
//        }
//        ShenyuContext shenyuContext = exchange.getAttribute(Constants.CONTEXT);
//        assert shenyuContext != null;
//        return Arrays.stream(rpcTypes).anyMatch(type -> Objects.equals(shenyuContext.getRpcType(), type.getName()));
//    }

    /**
     * the plugin execute skip except some rpc types.
     * if return true this plugin can not execute.
     *
     * <p>the same for:
     * <pre>
     * <code>!Objects.equals(rpcType, typeA.getName())
     * &amp;&amp; !Objects.equals(rpcType, typeB.getName())
     * &amp;&amp; !Objects.equals(rpcType, type...getName())
     * </code>
     * </pre>
     *
     * @param exchange the current server exchange
     * @param exceptRpcTypes the except rpc type list
     * @return current rpcType != someone exceptRpcType
     */
//    default boolean skipExcept(ServerWebExchange exchange, RpcTypeEnum... exceptRpcTypes) {
//        return !skip(exchange, exceptRpcTypes);
//    }

    /**
     * Skip the non http call.
     * if return true this plugin can not execute.
     *
     * @param exchange the current server exchange
     * @return http/spring cloud return true, others false.
     */
//    default boolean skipExceptHttpLike(ServerWebExchange exchange) {
//        return !skip(exchange, RpcTypeEnum.HTTP, RpcTypeEnum.SPRING_CLOUD);
//    }

    /**
     * Plugin before operation.
     *
     * @param exchange context
     */
    default void before(ServerWebExchange exchange) {
        System.out.println("before");
    }

    /**
     * Plugin after operation.
     *
     * @param exchange context
     */
    default void after(ServerWebExchange exchange) {
        long currentTimeMillis = System.currentTimeMillis();
//        long startTime = (long) exchange.getAttributes().get(Constants.PLUGIN_START_TIME + named());
//        LOG.debug("shenyu traceId:{}, plugin named:{}, cost:{}", exchange.getLogPrefix(), named(), currentTimeMillis - startTime);
//        exchange.getAttributes().remove(Constants.PLUGIN_START_TIME + named());
    }
}
